How a form submission is delivered

Clarification By design
A form with an id and data-attributes is submitted by Docly itself: the submission is mailed to the workspace owner, data-smtp only chooses the SMTP configuration that sends it, data-validate runs #/API/<name>.js first and must return true, data-antispam="on" adds the platform's own Turnstile check without any keys, and one IP address can submit at most 25 forms in 24 hours by default.
Applies to: FormsHash templatesAPI

What you'll see

You add a contact form to a page and expect to choose who receives it, or a form stops working with “Can't find form tag with id”, “Send failed due to configuration error” or “Too many form submissions from this IP address in a short time!”.

What's actually happening

Load the platform's submit script on the page — <script src="/vanilla.submitform.js"></script> (or jquery.submitform.js). Docly serves it when the site has no file of that name. The script posts the form back to the page, and the server then:

  1. Renders the page and finds the form by its id. The form must be in the page output with the same id, or the submission fails. The fields in that markup decide what is mailed.
  2. Builds the mail to the workspace owner — not the person who published the site, and not an address in the markup. The subject is FORM: <page title> (<form id>). Uploaded files are attached, and the sender's country and device are included. On a site that requires login, the signed-in user is included too.
  3. data-smtp names an SMTP configuration (a path such as #/MySmtp, or its id) to send through. It is not a recipient: anything that is not an SMTP configuration fails with “Send failed due to configuration error”.
  4. data-validate="Name" runs #/API/Name.js as an API script, with the posted fields as parameters and in form. It must return true. Any other return value, or a throw, rejects the submission; a thrown object is sent back as JSON with status 403.
  5. The per-IP limit: more than 25 submissions from one IP address in 24 hours are refused. An IP with an active developer session gets a higher limit (1000).
  6. data-antispam="on" — exactly on — makes the submit script show Docly's own Turnstile widget and the server verify the token. You need no keys and no validation function for it. Without a valid token the submission is refused.
  7. The mail is sent, and the visitor gets the text in data-message (or the content of the file named in data-message-file).

Submissions are not stored in the workspace; they exist only as mail.

What to do

<form id="Contact" data-antispam="on" data-message="Thank you, we will be in touch.">
  <input name="Name" required>
  <input name="Email" type="email" required>
  <textarea name="Message" required></textarea>
  <button type="submit">Send</button>
</form>
<script src="/vanilla.submitform.js"></script>
  • Give every form a unique, fixed id. It finds the form and appears in the subject.
  • Use data-antispam="on" unless you need your own Turnstile keys; see Protect every form with Turnstile for that route.
  • Need another recipient? Transfer the workspace, or handle the post in an API script with docly.sendForm() and an explicit address.
  • A workspace owner without a valid e-mail address gets no mail: the visitor sees “DELIVERY FAILED!”, and the site console says why.
  • Test the success path in a workspace you own — it mails a real person.